spring作为粘合剂,其中IOC是它的基础,即控制反转,将项目中对对象的创建、依赖,交给IOC容器来完成。而每一个对象创建方式都各不相同,那么IOC要集中管理这一切,肯定不是一件简单的工作。本篇将介绍IOC容器整体启动的过程。
BeanFactory
IOC容器,是一个典型的工厂模式实现,BeanFactory是IOC最顶层的接口,规范了IOC最基础的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException; <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException; <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isPrototype(String name) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
@Nullable Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name); }
|
BeanFactory有三个重要的子接口:ListableBeanFactory、AutowireCapableBeanFactory、HierarchicalBeanFactory,最后都由DefaultListableBeanFactory来实现,之所以分别定义这么接口,是为了区别每一个接口的使用场合,对对象的数据访问做限制。例如
- ListableBeanFactory 规范了bean的集合,表示bean可列表化。
- AutowireCapableBeanFactory 规范了bean的行为,表示自动装配规则。
- HierarchicalBeanFactory 规范了bean之间的关系,表示bean有继承关系,可能存在父bean。
我们通常说的ApplicationContext接口,是spring提供对BeanFactory功能增强的规范。spring提供了很多对IOC的实现,比如GenericApplicationContext、ClassPathXmlApplicationContext等。
BeanDefinition
每一个bean初始化的规则都不一样,我们通过xml或者注解配置bean的依赖关系后,spring会将其转换成BeanDefinition保存在IOC容器中,待bean真正创建的时候使用。所以BeanDefinition描述了整个bean的信息,包含依赖关系。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON; String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
int ROLE_APPLICATION = 0; int ROLE_SUPPORT = 1; int ROLE_INFRASTRUCTURE = 2;
void setParentName(@Nullable String parentName); String getParentName();
void setBeanClassName(@Nullable String beanClassName); String getBeanClassName();
void setScope(@Nullable String scope); String getScope();
void setLazyInit(boolean lazyInit); boolean isLazyInit();
void setDependsOn(@Nullable String... dependsOn); String[] getDependsOn();
void setAutowireCandidate(boolean autowireCandidate); boolean isAutowireCandidate(); void setPrimary(boolean primary); boolean isPrimary(); void setFactoryBeanName(@Nullable String factoryBeanName); String getFactoryBeanName(); void setFactoryMethodName(@Nullable String factoryMethodName); String getFactoryMethodName(); ConstructorArgumentValues getConstructorArgumentValues(); default boolean hasConstructorArgumentValues() { return !getConstructorArgumentValues().isEmpty(); } MutablePropertyValues getPropertyValues(); default boolean hasPropertyValues() { return !getPropertyValues().isEmpty(); }
boolean isSingleton(); boolean isPrototype(); boolean isAbstract(); int getRole(); String getDescription(); String getResourceDescription(); BeanDefinition getOriginatingBeanDefinition(); }
|
一路看下来,spring的方法名字感觉挺符合中国人取名字的习惯,一看就能懂得那种。所以也没有写得过细。
BeanDefinitionReader
看上面BeanDefinition所描述的信息,就知道bean解析非常复杂,而BeanDefinition中所描述的信息,spring都需要留出可扩展的地方,保证足够灵活,而xml解析过程由BeanDefinitionReader来完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public interface BeanDefinitionReader { BeanDefinitionRegistry getRegistry(); ResourceLoader getResourceLoader(); ClassLoader getBeanClassLoader(); BeanNameGenerator getBeanNameGenerator();
int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException; int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException; int loadBeanDefinitions(String location) throws BeanDefinitionStoreException; int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException; }
|
原理预透
IOC初始化,基本可以理解成两个动作。准备容器、加载BeanDefinition。而加载BeanDefinition大致过程分为:
- 由ResourceLoader来完成资源文件的定位
- 将Resource对象交给BeanDefinitionReader来完成解析
- 容器解析得到BeanDefinition后,需要在IOC中注册,由BeanDefinitionRegistry来完成
多说一句,BeanDefinitionRegistry的注册过程就是在IOC内部维护了一个Map,用来保存BeanDefinition,后续对bean的所有操作都围绕这个Map来完成。